/*
 * CCameraDevice.cpp
 *
 *  Created on: 2018年10月4日
 *      Author: zhengboyuan
 */

#include "stdafx.h"
#include "CCameraDevice.h"

BOOL CALLBACK CCameraDevice::MSGCallBack_V31(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen, void* pUser)
{
	CCameraDevice* pthis = (CCameraDevice*)pUser;
	pthis->msgCallback(lCommand, pAlarmer, pAlarmInfo, dwBufLen);
	return true;
}

void CALLBACK CCameraDevice::MSGCallBack(
	LONG               lCommand,
	NET_DVR_ALARMER    *pAlarmer,
	char               *pAlarmInfo,
	DWORD              dwBufLen,
	void               *pUser
	)
{
	CCameraDevice* pthis = (CCameraDevice*)pUser;
	pthis->msgCallback(lCommand, pAlarmer, pAlarmInfo, dwBufLen);
}

void CALLBACK CCameraDevice::ExceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle, void *pUser)
{
	CCameraDevice* pthis = (CCameraDevice*)pUser;
	pthis->exceptionCallBack(dwType, lUserID, lHandle);
}



CCameraDevice::CCameraDevice():
	m_user(-1),
	m_deviceInfo(),
	m_alarmHandle(-1),
	m_connected()
{
}

CCameraDevice::~CCameraDevice()
{
	close();
}

bool CCameraDevice::open(const Camera& camera)
{
	m_camera = camera;

	bool connected = login(m_camera.ip, m_camera.port, m_camera.user, m_camera.password);

	setConnected(connected);

	fireDeviceStatus(connected);

	return connected;
}

void CCameraDevice::close()
{
	logout();
}

bool CCameraDevice::isConnected()
{
	return m_user >= 0 && m_connected;
}

bool CCameraDevice::reconnect()
{
	bool connected = login(m_camera.ip, m_camera.port, m_camera.user, m_camera.password);

	setConnected(connected);

	fireDeviceStatus(connected);

	return connected;
}

LONG CCameraDevice::getLoginUser()
{
	return m_user;
}

void CCameraDevice::setConnected(bool connected)
{
	{
		comn::AutoCritSec lock(m_cs);
		m_connected = connected;
	}

	fireDeviceStatus(connected);
}

bool CCameraDevice::login(const std::string& ip, int port, const std::string& user, const std::string& password)
{
	bool done = false;

	NET_DVR_USER_LOGIN_INFO loginInfo = NET_DVR_USER_LOGIN_INFO();
	strcpy(loginInfo.sDeviceAddress, ip.c_str());
	loginInfo.wPort = port;
	strcpy(loginInfo.sUserName, user.c_str());
	strcpy(loginInfo.sPassword, password.c_str());
	m_user = NET_DVR_Login_V40(&loginInfo, &m_deviceInfo);

	//m_user = NET_DVR_Login_V30(const_cast<char*>(ip.c_str()), port,
	//	const_cast<char*>(user.c_str()), const_cast<char*>(password.c_str()), &m_deviceInfo);
	done = (m_user >= 0);
	if (done)
	{
		TRACE("login done. user: %d, ip: %s\n", m_user, ip.c_str());
		setupAlarm();
	}
	return done;
}

void CCameraDevice::logout()
{
	if (m_alarmHandle >= 0)
	{
		NET_DVR_CloseAlarmChan_V30(m_alarmHandle);
		m_alarmHandle = -1;
	}

	NET_DVR_Logout(m_user);
	m_user = -1;
}

void CCameraDevice::setupAlarm()
{
	//BOOL ret = NET_DVR_SetDVRMessageCallBack_V31(MSGCallBack_V31, this);
	BOOL ret = NET_DVR_SetDVRMessageCallBack_V50(m_user, MSGCallBack, this);
	TRACE("NET_DVR_SetDVRMessageCallBack_V50: %d\n", ret);

	//NET_DVR_SetDVRMessageCallBack(MessageCallBack, (DWORD)((void*)this));

	NET_DVR_SETUPALARM_PARAM alarmParam = { 0 };
	alarmParam.dwSize = sizeof(alarmParam);
	alarmParam.byAlarmInfoType = 0;
	m_alarmHandle = NET_DVR_SetupAlarmChan_V41(m_user, &alarmParam);
}

void CCameraDevice::msgCallback(LONG lCommand, NET_DVR_ALARMER *pAlarmer, char *pAlarmInfo, DWORD dwBufLen)
{
	TRACE("msgCallback. cmd: 0x%04x, user: %d\n", lCommand, pAlarmer->lUserID);
	if (pAlarmer->lUserID != m_user)
	{
		return;
	}

	if (lCommand == COMM_ALARM_PDC)
	{
		NET_DVR_PDC_ALRAM_INFO alarmInfo = NET_DVR_PDC_ALRAM_INFO();
		memcpy(&alarmInfo, pAlarmInfo, sizeof(alarmInfo));

		TRACE("mode: %d, chl: %d, smart: %d, byBrokenNetHttp: %d, enter: %d, leav: %d, pass: %d\n",
			alarmInfo.byMode,
			alarmInfo.byChannel, alarmInfo.bySmart,
			alarmInfo.byBrokenNetHttp,
			alarmInfo.dwEnterNum, alarmInfo.dwLeaveNum, alarmInfo.dwPassingNum);

		if (alarmInfo.byMode == 0)
		{
			{
				comn::AutoCritSec lock(m_cs);
				m_flowCount.enterNum = alarmInfo.dwEnterNum;
				m_flowCount.leaveNum = alarmInfo.dwLeaveNum;
			}

			fireFlowCount(m_flowCount);
		}
	}
}

void CCameraDevice::exceptionCallBack(DWORD dwType, LONG lUserID, LONG lHandle)
{
	TRACE("exceptionCallBack. dwType: 0x%04x, user: %d, handle: %d\n", dwType, lUserID, lHandle);
}